package Client;

import Utility.EncryptWithCertificate;
import Utility.Signatures;
import Utility.ValidateXMLSig;
import Utility.XMLUtility;
import Utility.exceptions.ExceptionCaricamentoProfilo;
import Utility.exceptions.ExceptionCertificatoNonCreato;
import Utility.exceptions.ExceptionChiaveNonTrovata;
import Utility.exceptions.ExceptionFirmaNonCorretta;
import Utility.exceptions.ExceptionGenerazioneChiavi;
import Utility.exceptions.ExceptionGenerazionePKCS10;
import Utility.exceptions.ExceptionNotFindSignature;
import Utility.exceptions.ExceptionSalvataggioFile;
import Utility.exceptions.ExceptionSalvataggioPem;
import Utility.exceptions.ExceptionStatusCertificato;
import Utility.exceptions.ExceptionVerificaFirma;
import com.itextpdf.text.DocumentException;
import java.io.*;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.*;
import java.security.cert.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.x500.X500Principal;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.ocsp.*;
import org.bouncycastle.asn1.pkcs.Attribute;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.ocsp.*;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.openssl.PasswordFinder;
import org.bouncycastle.util.encoders.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 *
 * @author Gonel
 */
public class Client {
    
    // chiavi pubblica e privata
    private KeyPair kp; // chiavi per la firma
    private Key pubKey;
    private Key privKey;
    private KeyPair kpCrit; // chiavi per la crittografia

    private String password = null; // password utilizzata per cifrare la chiave privata su file
    private String id = null; // id del client
    private String nome = null; // nome del client
    private String cognome = null; // cognome del client

    // certificato della CA
    private X509Certificate certCA;
    
    private X509CRL crl;
    
    /*
    * CA sulla quale fare chiamate
    * Lo inizializzo nel costruttore
    */
    /**
     *
     */
    public XmlRpcClient xmlRcpClient;        
        
    private static String FILE_CERTIFICATO_FIRMA = "my.cert";
    private static String FILE_CERTIFICATO_CRITTOGRAFIA = "myCrit.cert";
    /*
     * Costruttore del client
     */
    /**
     *
     * @param url_server
     */
    public Client(String url_server)
    {
        
        Security.addProvider(new BouncyCastleProvider());
        
        /*
         * Inizializzo il XmlRpcClient per la comuncazione con la CA
         */
        try {            
            XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
            config.setServerURL(new URL(url_server));
            config.setEnabledForExtensions(true);
            config.setConnectionTimeout(60 * 1000);
            config.setReplyTimeout(60 * 1000);
            xmlRcpClient = new XmlRpcClient();
            xmlRcpClient.setConfig(config);
            
            System.out.println("Client inizializzato");
            
        } catch (MalformedURLException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("Can't find server!");
        }
    }
        
    /**
     * Crea il profilo utente per la prima esecuzione del client
     * @param nome
     * @param cognome
     * @param organiz
     * @param unita
     * @param paese
     * @param email
     * @param pwd
     * @return
     * @throws Exception 
     */
    public boolean creaProfilo(String nome, String cognome, String organiz, String unita, String paese, String email, String pwd) throws Exception {

        id = nome + " " + cognome;
        this.nome = nome;
        this.cognome = cognome;

        // devo creare lo userinfo.xml
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

        // root elements
        Document doc = docBuilder.newDocument();
        Element rootElement = doc.createElement("userinfo");
        doc.appendChild(rootElement);

        // firstname elements
        Element firstname = doc.createElement("Name");
        firstname.appendChild(doc.createTextNode(nome));
        rootElement.appendChild(firstname);

        Element secondname = doc.createElement("Surname");
        secondname.appendChild(doc.createTextNode(cognome));
        rootElement.appendChild(secondname);

        Element organization = doc.createElement("Organization");
        organization.appendChild(doc.createTextNode(organiz));
        rootElement.appendChild(organization);

        Element unit = doc.createElement("Unit");
        unit.appendChild(doc.createTextNode(unita));
        rootElement.appendChild(unit);

        Element country = doc.createElement("Country");
        country.appendChild(doc.createTextNode(paese));
        rootElement.appendChild(country);

        Element mailaddress = doc.createElement("Email");
        mailaddress.appendChild(doc.createTextNode(email));
        rootElement.appendChild(mailaddress);

        // scrivo il tutto in un file xml
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource source = new DOMSource(doc);

        // creo le cartelle per le chiavi e per i certificati
        new File("key").mkdir();
        new File("cert").mkdir();
        
        StreamResult result = new StreamResult(new File("key/userinfo.xml"));
        transformer.transform(source, result);

        System.out.println("userinfo.xml creato");
        
        password = pwd;

        // carico il certificato della CA da file (preinstallato nel client)
        PEMReader pemReader= new PEMReader(new FileReader("ca/cert/my.cert"));
        certCA = (X509Certificate) pemReader.readObject();
       
        return true;
    }
	
    /**
    * Carica il profilo dell'utente all'avvio del client
    * @return true se il profilo viene caricato correttamente, falso altrimenti
    * @throws ParserConfigurationException
    * @throws SAXException
    * @throws IOException  
    */
    public boolean caricaProfilo() throws ParserConfigurationException, SAXException, IOException {
        try {
            // carico le info utente da file
            File fXmlFile = new File("key/userinfo.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc1 = dBuilder.parse(fXmlFile);
            doc1.getDocumentElement().normalize();
            NodeList nList = doc1.getElementsByTagName(doc1.getDocumentElement().getNodeName());

            String CN = null;
            String O = null;
            String OU = null;
            String C = null;
            String email = null;

            for (int temp=0; temp<nList.getLength();temp++){
                Node nNode= nList.item(temp);
                if(nNode.getNodeType()==Node.ELEMENT_NODE)
                {
                    Element eElement = (Element) nNode;
                    CN = getTagValue("Name",eElement)+ " " + getTagValue("Surname",eElement);
                    O = getTagValue("Organization",eElement);
                    OU = getTagValue("Unit",eElement);
                    C = getTagValue("Country",eElement);
                    email = getTagValue("Email",eElement);
                    nome = getTagValue("Name",eElement);
                    cognome =getTagValue("Surname",eElement);
                }
            }

            id=CN;

            // carica le chiavi per la firma
            readPubKey();
            readPrivKey();
            System.out.println("Lette chiavi RSA per la firma");

            // leggo le chiavi per la crittografia
            try {       
                readKeyCrit();
                System.out.println("Lette chiavi RSA per la crittografia");
            } catch (IOException ex) {
                System.out.println("Chiavi per la crittografia non ancora generate");
            }

            System.out.println("Caricati i dati dell'utente " + id);

            // carico il certificato della CA da file (preinstallato nel client)
            PEMReader pemReader= new PEMReader(new FileReader("ca/cert/my.cert"));
            certCA = (X509Certificate) pemReader.readObject();

            return true;
            
        } catch (ExceptionChiaveNonTrovata ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }
        
    /**
    * GESTISCE LA RICHIESTA DI CERTIFICATO CHE SIA DI FIRMA O CRITTOGRAFIA
    * @param tipo 
    * @param dimensione_chiave 
    * @return true if the CA receive the request
    * @throws XmlRpcException
    * @throws ExceptionGenerazioneChiavi
    * @throws ExceptionFirmaNonCorretta
    * @throws ExceptionCaricamentoProfilo 
    * @throws ExceptionGenerazionePKCS10 
    * @throws ExceptionSalvataggioPem
    * @throws ExceptionVerificaFirma
    * @throws ExceptionSalvataggioFile  
    */
    public int richiediCertificato(int tipo, int dimensione_chiave) throws XmlRpcException, ExceptionGenerazioneChiavi, ExceptionFirmaNonCorretta, ExceptionCaricamentoProfilo, ExceptionGenerazionePKCS10, ExceptionSalvataggioPem, ExceptionSalvataggioFile, ExceptionVerificaFirma{                       
        // Status da ritornare
        int status;

        // Variabile stringa sul tipo di certificato per la creazione del nome file di PKCS10
        String nomefilePKCS10;
        String nomefilechiave;

        if(tipo == Utility.Utility.FIRMA){
            nomefilePKCS10 = Utility.Utility.NOME_FILE_PKCS10_FIRMA;
            nomefilechiave = Utility.Utility.NOME_FILE_CHIAVE_FIRMA;
        }else{
            nomefilePKCS10 = Utility.Utility.NOME_FILE_PKCS10_CRITTOGRAFIA;
            nomefilechiave = Utility.Utility.NOME_FILE_CHIAVE_CRITTOGRAFIA;
        }

        status = this.richiediCertificato(tipo, dimensione_chiave, nomefilePKCS10, nomefilechiave);

        return status;
    }

    /**
    * Genera la richiesta PKCS10 e la invia alla CA.
    * 1) Genera le chiavi (per il tipo di certificato richiesto) e le salva nell'hd
    * 2) Carica le informazioni dell'utente
    * 3) Genera il pkcs10 con le nuove chiavi e le informazioni dell'utente
    * 4) Salva il pkcs10 nello storico
    * 5) Salva le chiavi
    * 6) Invia la richiesta xml firmata con pkcs10 al server
    * 7) Controlla la firma della risposta del server
    * 8) Ritorna la risposta del server
    * @return true se la CA riceve la richiesta
    * @throws XmlRpcException 
    */
    private int richiediCertificato(int tipo, int dimensione_chiave, String nomefile, String nomechiave) throws XmlRpcException, ExceptionGenerazioneChiavi, ExceptionFirmaNonCorretta, ExceptionCaricamentoProfilo, ExceptionGenerazionePKCS10, ExceptionSalvataggioPem, ExceptionSalvataggioFile, ExceptionVerificaFirma{
        
        System.out.println("\n---------------------\nINVIO RICHIESTA DI CERTIFICATO ");
        
        // Generazione delle chiavi con l'algoritmo RSA
        System.out.println("GENERAZIONE DELLE CHIAVI");
        this.generazioneChiaviRsa(tipo, dimensione_chiave, nomechiave);

        System.out.println("CARICAMENTO DATI UTENTE");
        String CN = null;
        String O = null;
        String OU = null;
        String C = null;
        String email = null;
        String nome_user = null;
        String cognome_user = null;
        try{
            File fXmlFile = new File("key/userinfo.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc1 = dBuilder.parse(fXmlFile);
            doc1.getDocumentElement().normalize();
            NodeList nList = doc1.getElementsByTagName(doc1.getDocumentElement().getNodeName());		

            for (int temp=0; temp<nList.getLength();temp++){
                Node nNode= nList.item(temp);
                if(nNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    Element eElement = (Element) nNode;
                    nome_user = getTagValue("Name",eElement);
                    cognome_user = getTagValue("Surname",eElement);                
                    CN = nome_user+ " " + cognome_user;
                    O = getTagValue("Organization",eElement);
                    OU = getTagValue("Unit",eElement);
                    C = getTagValue("Country",eElement);
                    email = getTagValue("Email",eElement);

                }
            }
        // caricati tutti i dati dell'utente			
        }catch(Exception e){
            throw new ExceptionCaricamentoProfilo();
        }
        System.out.println("CARICATE INFORMAZIONI UTENTE");                        

        // Genero il PKCS10
        System.out.println("GENERAZIONE PKCS10"); 
        PKCS10CertificationRequest pkcs10req = null;
        try{
            GeneralNames subjectAltName = new GeneralNames(new GeneralName(GeneralName.rfc822Name, email)); 
            Vector oids = new Vector(); 
            Vector values = new Vector(); 
            oids.add(X509Extensions.SubjectAlternativeName); 
            values.add(new X509Extension(false, new DEROctetString(subjectAltName))); 

            // Importo le info della chiave 
            KeyUsage k = new KeyUsage(0); 
            oids.add(X509Extensions.KeyUsage); 
            values.add(new X509Extension(true, new DEROctetString(k))); 
            X509Extensions extensions = new X509Extensions(oids, values); 
            Attribute attribute = new Attribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest,new DERSet(extensions)); 
            pkcs10req = new PKCS10CertificationRequest("SHA256WithRSAEncryption", 
            new X500Principal("CN=" + CN + ", O=" + O + ", OU=" + OU 
            + ", C=" + C), (PublicKey)getPubKey(), new DERSet( 
            attribute), (PrivateKey) getPrivKey()); 
            // Creata la richiesta PKCS10
            System.out.println("PKCS10 GENERATO"); 
        }catch(Exception e){
            throw new ExceptionGenerazionePKCS10();
        }
        System.out.println("CREATO IL PKCS10"); 

        System.out.println("SALVATAGGIO PKCS10 PER LO STORICO");                                    
        // Salvo la richiesta precedente per lo storico
        String old = new SimpleDateFormat("dd-MM-yyyy_HH-mm").format(new Date());
        //calcolo il futuro nome del file da rinominare
        String oldP10 = (String) "cert/"+nomefile+"-"+old+".p10";
        //System.out.println("\tOldP10: "+oldP10);

        // rinomino quella precedente se c'è
        File oldPkcs10Req = new File("cert/"+nomefile+".p10");
        oldPkcs10Req.renameTo(new File(oldP10));

        //salvo in pem la richiesta PKCS10 
        try{
            FileWriter sw = new FileWriter("key/"+nomefile+".p10"); 
            PEMWriter pemWrt = new PEMWriter(sw); 
            pemWrt.writeObject(pkcs10req); 
            pemWrt.close();          
        }catch(Exception e){
            throw new ExceptionSalvataggioPem("key/"+nomefile+".p10");
        }

        //rinomino la richiesta precendente
        File oldPkcs10ReqXML = new File("cert/"+nomefile+".xml");

        String oldXML = (String)"cert/"+nomefile+"-"+old+".xml";
        //System.out.println("\tOldP10: "+oldXML);
        oldPkcs10ReqXML.renameTo(new File(oldXML));

        // USARE FIRMA DI UTILITY XML
        System.out.println("CREO XML CON PARAMETRI DA INVIARE");
        byte[] coded = Base64.encode(pkcs10req.getEncoded());
        String strCoded = new String(coded);                  
        Document doc = XMLUtility.getDocumentPKCS10(strCoded,CN, Integer.toString(tipo), nome_user, cognome_user, O, OU, C, email); 
        System.out.println("FIRMO XML DA INVIARE");
        XMLUtility.firmaDocumento(doc,this.getPrivKey(), this.pubKey);  
        
        // Salvo la richiesta attuale
        try{
            OutputStream os = new FileOutputStream(new File("cert/"+nomefile+".xml"));
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            trans.transform(new DOMSource(doc), new StreamResult(os));	                       
        }catch(Exception e){
            throw new ExceptionSalvataggioFile("cert/"+nomefile+".xml");
        }

        // chiamo la CA                   
        System.out.println("INVIO RICHIESTA ALLA CA");                                    
        Vector params = new Vector(); // no parametri 
        params.add(doc);

        Object result = this.xmlRcpClient.execute("ServiziCA.richiediCertificato", params);
        System.out.println("RISPOSTA RICEVUTA DALLA CA");                                    

        /*
        * Cast di risposta Document
        * La CA mi manda lo status di risposta in un Document firmato
        */
        Document status_sign = (Document)result;

        // Estraggo lo status
        String status = XMLUtility.getValueStringInXML(status_sign, "status");

        // Controllo la validazione della risposta        
        boolean validate = false;        
        try {
            validate = ValidateXMLSig.validateDigitalSignature(status_sign,certCA.getPublicKey());
        } catch (Exception ex) {
            throw new ExceptionVerificaFirma(Client.class.getName());
        }
        
        if(validate)
        {
            System.out.println("RISPOSTA RICEVUTA VALIDATA. RITORNO ALLA GUI STATUS: "+status);
        }
        else{
            throw new ExceptionFirmaNonCorretta();                     
        }

        /*
        * - Ritorna 1 se e' andato tutto a buon fine, altrimenti 0
        * - Ritorna 2 se è presente in coda una richiesta uguale
        * - Ritorna 3 se la validazione del digital signature del messaggio arrivato alla CA ha esito negativo
        */
        System.out.println("--------------------\n");        
        return Integer.parseInt(status);
    }

    /**
     * Genera le chiavi RSA
     * Le chiavi vengono salvate come attributo del client. Per questo viene chiesto il tipo come parametro
     * Le chiavi vengono salvate nell'HD e per questo viene chiesto il nome del file come parametro.
     * @param tipo: 1 per firma, 2 per crittografia
     * @param bits: i bit di lunghezza della chiave
     * @param nomechiave: nome per il file
     * @return un KeyPair
     * @throws Exception
     * @throws Exception 
     */
    private KeyPair generazioneChiaviRsa(int tipo, int bits, String nomechiave) throws ExceptionGenerazioneChiavi{
        try {
            // generazione chiavi RSA
            Security.addProvider(new BouncyCastleProvider());

            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
            generator.initialize(bits);
            KeyPair pair = generator.generateKeyPair();

            if(tipo==Utility.Utility.FIRMA){
                pubKey = (Key) pair.getPublic();
                privKey = (Key) pair.getPrivate();
            }else{
                kpCrit = generator.generateKeyPair();
            }

            //salvataggio chiave pubblica
            FileWriter file = new FileWriter("key/pub"+nomechiave+".pem");
            PEMWriter pemWriter  = new PEMWriter(file);
            pemWriter.writeObject(pubKey);
            pemWriter.close();
            file.close();
            // chiave pubblica salvata

            // salvataggio chiave privata
            char[] passwordc = password.toCharArray();
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            FileWriter sw = new FileWriter("key/priv"+nomechiave+".pem");

            PEMWriter pemWrt = new PEMWriter(sw);
            pemWrt.writeObject(getPrivKey(), "DES-EDE3-CBC", passwordc, random);
            pemWrt.close();

            System.out.println("Chiavi create e salvate");
            return pair;
        } catch (Exception ex) {
            throw new ExceptionGenerazioneChiavi();
        } 
    }
    
    /**
     * Controllo lo status del certificato
     * con una chiamata sicura alla CA
     * @param tipo
     * @return
     * @throws XmlRpcException, ExceptionNotFindSignature, IllegalAccessException, InstantiationException, ClassNotFoundException, MarshalException, XMLSignatureException, ExceptionFirmaNonCorretta 
     */
    private int getStatusCertificato(String tipo) throws XmlRpcException, ExceptionNotFindSignature, IllegalAccessException, InstantiationException, ClassNotFoundException, MarshalException, XMLSignatureException, ExceptionFirmaNonCorretta{

        System.out.println("\n-----------------");
        // Creo il file xml che contiene i parametri: id e tipo. Il file xml mi serve per firmarlo nel digsign
        Document richiestaStatusXML = XMLUtility.getDocumentIdTipo(id, tipo);

        // Firmo il documento
        //richiestaStatusXML = XMLUtility.firmaDocumento(richiestaStatusXML, this.getPrivKey(), (PublicKey)this.pubKey);
        richiestaStatusXML = XMLUtility.firmaDocumento(richiestaStatusXML, this.getPrivKey(), (PublicKey)this.pubKey);                       

        /*
        * Parametri da inviare
        * Invio il documento xml firmato con i paramentri al suo interno
        * per una comunicazione sicura
        */
        Vector params = new Vector();          
        params.add(richiestaStatusXML);

        // faccio la richiesta
        System.out.println("RICHIEDO SE C'È IL CERTIFICATO DI TIPO: " + tipo + " DELL'UTENTE: "+id);
        Object result = this.xmlRcpClient.execute("ServiziCA.getCertStatusByUsername", params);
        System.out.println("RICEVO RISPOSTA DI STATUS DALLA CA");

        // Converto in document la risposta del sever
        Document doc_status = (Document)result;        
        // Controllo la validazione della risposta
        boolean validate = ValidateXMLSig.validateDigitalSignature(doc_status,certCA.getPublicKey());
        if(!validate){
            System.out.println("RICEVO CERTIFICATO: Ma firma della risposta del server non validata\n");
            throw new ExceptionFirmaNonCorretta();
        }

        // Estraggo lo status
        String status = XMLUtility.getValueStringInXML(doc_status, "status");        

        System.out.println("-----------------\n");
        return Integer.parseInt(status);
    }
            
        /**
         * Interroga la CA per vedere se il certificato e' pronto, e in questo caso lo recupera
         * Prima di recuperare il certificato devo controllare che il certificato sia  pronto:
         * 1) Creo un file xml con id, tipo
         * 2) Firmo il documento xml
         * 3) Invio alla CA il documento firmato
         * 
         * La CA riceve il documento firmato
         * 1) Controlla che sia valido
         * 2) Estrae l'id
         * 3) Estrae il tipo
         * 4) Controlla se il certificato è pronto
         * 5) Ritorna in un documento xml firmato la risposta 
         *  0 inesistente
         *  1 pronto
         *  2 errore nella firma durante la comunicazione
         * 
         * Se il certificato è pronto allora procedo nello stesso modo a fare la richiesta
         * @param tipo_certificato 
         * @return 
         * @throws ExceptionFirmaNonCorretta
         * @throws ExceptionCertificatoNonCreato 
         * @throws XmlRpcException
         * @throws ExceptionVerificaFirma 
         * @throws ExceptionStatusCertificato 
         * @throws ExceptionSalvataggioPem  
         */
        public boolean ottieniCertificato(int tipo_certificato) throws ExceptionFirmaNonCorretta, ExceptionCertificatoNonCreato, XmlRpcException, ExceptionVerificaFirma, ExceptionStatusCertificato, ExceptionSalvataggioPem{
            System.out.println("\n----------------\nOTTIENI CERTIFICATO DI TIPO "+tipo_certificato+" DALLA CA");
       
            String tipo = String.valueOf(tipo_certificato);
            int result_status_certificato = 0;
            try {
                result_status_certificato = this.getStatusCertificato(tipo);
            } catch (ExceptionNotFindSignature ex) {
                throw new ExceptionStatusCertificato();
            } catch (IllegalAccessException ex) {
                throw new ExceptionStatusCertificato();
            } catch (InstantiationException ex) {
                throw new ExceptionStatusCertificato();
            } catch (ClassNotFoundException ex) {
                throw new ExceptionStatusCertificato();
            } catch (MarshalException ex) {
                throw new ExceptionStatusCertificato();
            } catch (XMLSignatureException ex) {
                throw new ExceptionStatusCertificato();
            }
 

            // Controlla lo status del certificato alla CA.
            // 0: ancora inesistente
            // 1: il certificato è pronto    
            // 2: c'è stato un errore nella verifica della firma nella comunicazione

            // Errore: certificato non pronto
            if((Integer)result_status_certificato == 0){
                System.out.println("CERTIFICATO NON PRONTO O INESISTENTE: "+result_status_certificato);
            }
            else 
                // Errore: nella verifica della firma
                if((Integer)result_status_certificato == 2){
                    System.out.println("FIRMA NON CORRETTA NELLA RICHIESTA DELLO STATO DEL CERTIFICATO");                   
                }
                else // tutto ok risposta 1
                {
                    /*
                     * La CA mi ha risposto che il certificato e' pronto. Lo devo chiedere e lo salvo nel mio database
                     * 
                     */
                    System.out.println("CERTIFICATO PRONTO PER ESSERE OTTENUTO");                   

                    // Creo il file xml che contiene i parametri: id e tipo. Il file xml mi serve per firmarlo nel digsign
                    Document richiestaCertificatoXML = XMLUtility.getDocumentIdTipo(id, tipo);

                    // Firmo il documento
                    //richiestaStatusXML = XMLUtility.firmaDocumento(richiestaStatusXML, this.getPrivKey(), (PublicKey)this.pubKey);
                    richiestaCertificatoXML = XMLUtility.firmaDocumento(richiestaCertificatoXML, this.getPrivKey(), this.getPubKey());            

                    // Stampo la richiesta del certificato
                    System.out.println("RICHIESTA DEL CERTIFICATO");

                    // Preparo i parametri per richiedere il certificato: il documento xml
                    Vector params_richiesta_certificato = new Vector(); // no parametri 
                    params_richiesta_certificato.add(richiestaCertificatoXML);
    
                    System.out.println("RECUPERO CERTIFICATO DI TIPO: " + tipo + " DI: "+id);
                    // Mi ritorna il documento xml firmato con il certificato
                    Object result2 = this.xmlRcpClient.execute("ServiziCA.getCertByUsername", params_richiesta_certificato);

                    // Converto in document la risposta del sever
                    Document doc_certificato = (Document)result2;

                    // Controllo la validazione della risposta
                    boolean validate = false;
                    try{
                        validate = ValidateXMLSig.validateDigitalSignature(doc_certificato,certCA.getPublicKey());
                    }catch(Exception e){
                        throw new ExceptionVerificaFirma(e.getMessage());
                    }
                    if(!validate){
                        System.err.println("RICEVO CERTIFICATO: Ma firma della risposta del server non validata");
                    }

                    // Estraggo lo status
                    String certificato = XMLUtility.getValueStringInXML(doc_certificato, "certificato");               
                    X509Certificate certificatoX509 = Utility.Utility.creaCertificatoDaStringa(certificato);

                    //System.out.println("CERTIFICATO OTTENUTO: " + certificatoX509);
                    System.out.println("CERTIFICATO OTTENUTO");

                    // Rinomina del certificato attuale se c'è
                    try{
                        System.out.println("RECUPERO IL SERIAL NUMBER DELL'ULTIMO CERTIFICATO SALVATO");
                        String nome_file;
                        if(tipo_certificato == Utility.Utility.FIRMA) {
                            nome_file = Client.FILE_CERTIFICATO_FIRMA;
                        }
                        else {
                            nome_file = Client.FILE_CERTIFICATO_CRITTOGRAFIA;
                        }
                        BigInteger sn_vecchio = Client.getSerialNumber(nome_file);
                        System.out.println("ULTIMO SERIAL NUMBER CERTIFICATO SALVATO: "+sn_vecchio);
                        BigInteger sn_attuale = certificatoX509.getSerialNumber();
                        System.out.println("ULTIMO SERIAL NUMBER CERTIFICATO OTTENUTO: "+sn_attuale);
                        if(!sn_attuale.equals(sn_vecchio)){                    
                            System.out.println("SALVATAGGIO DEL VECCHIO FILE NELLO STORICO");                                    
                            // Salvo la richiesta precedente per lo storico
                            String data_oggi = new SimpleDateFormat("dd-MM-yyyy_HH-mm").format(new Date());
                            //calcolo il futuro nome del file da rinominare
                            String nuovo_nome_certificato_vecchio = "cert/"+data_oggi+"-"+nome_file;

                            // rinomino quella precedente se c'è
                            File oldPkcs10Req = new File("cert/"+nome_file);
                            oldPkcs10Req.renameTo(new File(nuovo_nome_certificato_vecchio)); 
                            System.out.println("RINOMINATO VECCHIO FILE IN: "+nuovo_nome_certificato_vecchio); 
                        }else{
                            System.out.println("HO GIÀ QUESTO CERTIFICATO");
                        }               

                    }catch(FileNotFoundException e){
                        System.out.println("NON C'È NESSUN CERTIFICATO SALVATO NELLO STORICO");
                    }catch(IOException e){
                        System.out.println("NON C'È NESSUN CERTIFICATO SALVATO NELLO STORICO");
                    }                

                    String fileCertificato;
                    if(tipo_certificato==1){
                        fileCertificato="cert/"+Client.FILE_CERTIFICATO_FIRMA;
                    }else{
                        fileCertificato="cert/"+Client.FILE_CERTIFICATO_CRITTOGRAFIA;
                    }

                    // salvataggio del certificato su file pem
                    try{
                        FileWriter cf;
                        cf = new FileWriter(fileCertificato);
                        PEMWriter pemWriter = new PEMWriter(cf);
                        pemWriter.writeObject(certificatoX509);
                        pemWriter.flush();
                        pemWriter.close();
                    }catch(Exception e){
                        throw new ExceptionSalvataggioPem(fileCertificato);
                    }

                    System.out.println("NUOVO CERTIFICATO SALVATO");
                    System.out.println("-----------------\n");

                    return true;
                }
        
            System.out.println("-----------------\n");
            return false;
        }
        
    /**
     * Richiede la revoca del certificato alla CA
     * tipo : 1 se certificato di firma, 2 se di crittografia
     * @param tipo 
     * @return
     * @throws FileNotFoundException
     * @throws IOException  
     * 
    * 0 nessuna revoca    
    * 1 se ok
    * 2 se firma non valida
    * 3 errore nella verifica della firma    
    * 4 qualche errore nel database
    * 5 firma risposta non valida
   
     */
    public int revocaCertificato(int tipo) throws XmlRpcException, ExceptionVerificaFirma{

        System.out.println("\n---------------\n"
                + "RICHIEDO REVOCA DI CERTIFICATO DI TIPO: " + tipo);

        // costruisco il file xml con id e tipo di certificato, per inviarlo alla CA
        String tipoStringa =  String.valueOf(tipo); 
        System.out.println("CREO DOCUMENTO XML");
        Document richiestaCRLXML = XMLUtility.getDocumentIdTipo(id,tipoStringa);
        // firmo il documento
        System.out.println("FIRMO DOCUMENTO XML");
        richiestaCRLXML = XMLUtility.firmaDocumento(richiestaCRLXML, this.getPrivKey(), (PublicKey)this.pubKey);            

        // Chiamo il metodo revocaCertificato della CA, che mi restituisce un xml con l'esito della revoca
         Vector params_richiesta = new Vector();  
         params_richiesta.add(richiestaCRLXML);

         System.out.println("INVOCO CHIAMATA ALLA CA");
         Object result = this.xmlRcpClient.execute("ServiziCA.revocaCertificato", params_richiesta);

         // Controllo la validità del documento ritornato dalla CA
          Document doc_esito = (Document)result;
          boolean validate = false;
          
        try {
            validate = ValidateXMLSig.validateDigitalSignature(doc_esito,certCA.getPublicKey());
        } catch (Exception ex) {
            throw new ExceptionVerificaFirma(ex.getMessage());
        }
        
        if(!validate){
            System.err.println("FIRMA NON VALIDA");
            return 5;
        }else{
            System.out.println("FIRMA VALIDA");
        }

        String esitoStringa = XMLUtility.getValueStringInXML(doc_esito, "status");                        
        int esito = Integer.parseInt(esitoStringa);        
        return esito;
    }
        
    /**
     * Rinnovo il certificato di Firma (1) o di Crittografia (2)
     * @param tipo: 1 per firma, 2 per crittografia
     * @param bits: lunghezza chiave
     * @param tipo: nome della chiave per il salvataggio su disco
     * 0 rinnovo fallito
     * 1 rinnovo con successo
     * 2 firma non valida* 
     * @return 
     */
    public int rinnovoCertificato(int tipo, int bits, String nomechiave) throws ExceptionGenerazioneChiavi, ParserConfigurationException, XmlRpcException, ExceptionVerificaFirma, ExceptionFirmaNonCorretta
    {  
        //primo passo genero le chiavi
        System.out.println("\n---------------------");
        System.out.println("RICHIESTA DI RINNOVO");
        System.out.println("GENERO LE CHIAVI");
        KeyPair newKeyPair;                   
        try {
            newKeyPair = this.generazioneChiaviRsa(tipo, bits, nomechiave);
        } catch (ExceptionGenerazioneChiavi ex) {
            throw new ExceptionGenerazioneChiavi();
        }
        
        System.out.println("GENERO DOCUMENTO XML DA FIRMARE (chiavi, username, tipo) ("+newKeyPair+" "+nome+" "+cognome+" "+tipo+")");
        Document richiestaRinnovoCertificatoXML = XMLUtility.getDocumentRinnovoCertificato(newKeyPair, nome, cognome , tipo);
        
        // Firmo il documento xml
        System.out.println("FIRMO IL DOCUMENTO DA INVIARE");        
        richiestaRinnovoCertificatoXML = XMLUtility.firmaDocumento(richiestaRinnovoCertificatoXML, this.getPrivKey(), (PublicKey)this.pubKey);                       
        
        // Preparo i parametri
        Vector params = new Vector();          
        params.add(richiestaRinnovoCertificatoXML);

        // faccio la richiesta
        System.out.println("INVIO LA RICHIESTA DI RINNOVO");
        Object result = this.xmlRcpClient.execute("ServiziCA.rinnovoCertificato", params);
        System.out.println("RICEVO RISPOSTA DI RINNOVO DALLA CA");

        // Converto in document la risposta del sever
        Document doc_status = (Document)result;        
        // Controllo la validazione della risposta
        boolean validate;
        try {
            validate = ValidateXMLSig.validateDigitalSignature(doc_status,certCA.getPublicKey());
        } catch (Exception ex) {
            throw new ExceptionVerificaFirma(ex.getMessage());
        }
        
        if(!validate){
            System.out.println("FIRMA RISPOSTA NON VALIDA");
            throw new ExceptionFirmaNonCorretta();
        }else{
            System.out.println("FIRMA RISPOSTA VALIDA");
        }

        // Estraggo lo status
        String status = XMLUtility.getValueStringInXML(doc_status, "status");        

        System.out.println("---------------------\n");
        
        return Integer.parseInt(status);
        
    }
        
        
    /**
     * Ottiene la CRL alla CA
     * @return una CRL
     * @throws CRLException
     * @throws CertificateException
     * @throws XmlRpcException  
     */
    public X509CRL ottieniCrl() throws CRLException, CertificateException, XmlRpcException{
        
        X509CRL Crl = null;

        try {
            System.out.println("Richiedo Crl alla CA");
            Vector params_richiesta = new Vector();  
            Object result = this.xmlRcpClient.execute("ServiziCA.retrieveCRL", params_richiesta);
    
            // Controllo la validità del documento ritornato dalla CA
             Document doc_crl = (Document)result;
             boolean validate = ValidateXMLSig.validateDigitalSignature(doc_crl,certCA.getPublicKey());
             if(!validate){
                 System.err.println("RICEVO RISPOSTA: Ma firma della risposta del server non validata");
             }
             
             System.out.println("Ottenuta Crl dalla CA");

            // estrapolo la CRL dal documento di risposta
             String crlStringa = XMLUtility.getValueStringInXML(doc_crl, "crl");                

            // Da stringa lo converto in byte e da byte in javax..X509Certificate ... e poi da javax a java.X509Certificate...
            String strDecoded1 = crlStringa;

            byte[] decoded = Base64.decode(strDecoded1);

            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream is = new ByteArrayInputStream(decoded);
            Crl = (X509CRL)cf.generateCRL(is);

            return Crl;
            
        } catch (ExceptionNotFindSignature ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } catch (MarshalException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } catch (XMLSignatureException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } 
        
        return Crl;
    }
        
    /**
     * DEPRECATA - Chiedo alla CA di controllare la validità di un certificato tramite protocollo OCSP
     * @param certificato
     * @return
     * @throws XmlRpcException
     * @throws CertificateEncodingException
     * @throws ExceptionNotFindSignature 
     * @throws IllegalAccessException 
     * @throws ClassNotFoundException
     * @throws InstantiationException 
     * @throws XMLSignatureException
     * @throws ExceptionFirmaNonCorretta
     * @throws MarshalException  
     */    
    public int getStatusValiditaCertificatoOCSP(X509Certificate certificato) throws XmlRpcException, CertificateEncodingException, ExceptionNotFindSignature, IllegalAccessException, InstantiationException, ClassNotFoundException, MarshalException, XMLSignatureException, ExceptionFirmaNonCorretta{

            System.out.println("\nINVIO RICHIESTA OCSP VALIDITÀ CERTIFICATO ");

            byte[] certCoded = Base64.encode(certificato.getEncoded());
            String strCertCoded = new String(certCoded);  
            
            // Creo il file xml che contiene il parametro: certificato. Il file xml mi serve per firmarlo nel digsign
            Document richiestaXMLRevocaOCSP = XMLUtility.getDocumentCertificato(strCertCoded);
            
            // Stampo il documento XML con la richiesta di certificato
            //XMLUtility.printDocumentXML(richiestaXMLRevocaOCSP);

            // Firmo il documento
            richiestaXMLRevocaOCSP = XMLUtility.firmaDocumento(richiestaXMLRevocaOCSP, this.getPrivKey(), (PublicKey)this.pubKey);        
            
            /*
            * Parametri da inviare
            * Invio il documento xml firmato con i paramentri al suo interno
            * per una comunicazione sicura
            */
            Vector params = new Vector();            
            params.add(richiestaXMLRevocaOCSP);

            // faccio la richiesta
            Object result = this.xmlRcpClient.execute("ServiziCA.getControlloOCSP", params);
            
            System.err.println("RISPOSTA RICEVUTA DALLA CA. VERIFICA IN CORSO ");
            
            // Converto in document la risposta del sever
            Document doc_certificato = (Document)result;

            // Controllo la validazione della risposta
            boolean validate = ValidateXMLSig.validateDigitalSignature(doc_certificato,certCA.getPublicKey());
            if(!validate){
                throw new ExceptionFirmaNonCorretta();
            }
                
            // Estraggo lo status
            String status = XMLUtility.getValueStringInXML(doc_certificato, "status");                                                
            System.out.println("RISPOSTA OCSP ALLA RICHIESTA DI VALIDITÀ CERTIFICATO: "+status);            
            System.out.println("\n");
            
            return (Integer) result;
    }        
        
    /** Legge la chiave pubblica da file */
    private void readPubKey() throws ExceptionChiaveNonTrovata{
        try {
            PEMReader pemReader;
            pemReader = new PEMReader(new FileReader("key/pubKeyFirma.pem"));
            //KeyPair kp= null;
            pubKey = (Key) pemReader.readObject();
        } catch (IOException ex) {
            throw new ExceptionChiaveNonTrovata();
        }
    }
        
    /** Legge la chiave privata da file */
    private void readPrivKey() throws IOException{

        kp = null;

        try {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

        FileReader fr = new FileReader("key/privKeyFirma.pem");
        PEMReader readKP = new PEMReader(fr, new PasswordFinder() {
            public char[] getPassword() {
                return password.toCharArray();
            }
        });

        kp = (KeyPair) readKP.readObject();           
        privKey= kp.getPrivate();
    }

        
    /** Legge le chiavi per la crittografia dai file e le salva nel KeyPair kpCrit */
    private void readKeyCrit() throws IOException{

        PEMReader pemReader= new PEMReader(new FileReader("key/pubKeyCrittografia.pem"));
        
        //KeyPair kp= null;
        PublicKey pubKeyCrit = (PublicKey) pemReader.readObject();

        kpCrit = null;

        try {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }

        FileReader fr = new FileReader("key/privKeyCrittografia.pem");
        PEMReader readKP = new PEMReader(fr, new PasswordFinder() {
            public char[] getPassword() {
                return password.toCharArray();
            }
        });

        KeyPair soloPrivata = (KeyPair)readKP.readObject();
        kpCrit = new KeyPair(pubKeyCrit,soloPrivata.getPrivate()) ;

    }

    private Key getPubKey(){
            return pubKey;
    }

    private Key getPrivKey(){
            return privKey;
    }

    /**
     *
     * @param pwd
     */
    public void setPassword(String pwd){
            password = pwd;
    }

    /**
     * 
     * @param sTag: nome del tab
     * @param eElement: struttura xml
     * @return 
     */
    private static String getTagValue(String sTag, Element eElement){
            NodeList nList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
            Node nValue= (Node) nList.item(0);
            return nValue.getNodeValue();
    }   
    
       /**
        * Legge un certificato da file
        * @param tipo 
        * @return il certificato letto
        * @throws FileNotFoundException
        * @throws IOException 
        */
	private X509Certificate readCertificateFile(int tipo) throws FileNotFoundException, IOException{
            String fileCertificato;
            if(tipo==1){
                fileCertificato="cert/my.cert";
            }else{
                fileCertificato="cert/myCrit.cert";
            }
        PEMReader pemReader= new PEMReader(new FileReader(fileCertificato));
        X509Certificate cert = (X509Certificate) pemReader.readObject();
        
        return cert;
        
        }
        
        /**
         * Ritorna il serial number del certificato salvato su disco
         * @param filename: nome del file (all'interno della cartella cert)
         * @return il serial number del certificato
         * @throws FileNotFoundException
         * @throws IOException 
         */
	private static BigInteger getSerialNumber(String filename) throws FileNotFoundException, IOException{
            String fileCertificato="cert/"+filename;        
            PEMReader pemReader= new PEMReader(new FileReader(fileCertificato));
            X509Certificate cert = (X509Certificate) pemReader.readObject();
            return cert.getSerialNumber();        
        }
            
    /**
     * Firma un pdf con il certificato di firma del client
     * @param file 
     * @return 0 se tutto va bene, 1 altrimenti
     * @throws GeneralSecurityException 
     * @throws IOException
     * @throws DocumentException  
     */    
    public int firmaPdf(File file) throws GeneralSecurityException, IOException, DocumentException{
    
            Signatures sign = new Signatures();
            sign.signPdfFirstTime(file.getPath(),file.getParent()+"/firmato.pdf", readCertificateFile(1), (PrivateKey)privKey);
           // sign.signPdfSecondTime(file.getParent()+"/intermedio.pdf", file.getParent()+"/firmato.pdf", readCertificateFile(1), (PrivateKey)getPrivKey());
            return 0;
            
    }
    
    
    /**
     * Verifica un pd firmato con il certificato del client
     * @param file 
     * @param certificato 
     * @return 
     * @throws IOException
     * @throws XmlRpcException  
     */
    public int verificaPdfFirmato(File file, File certificato) throws IOException, XmlRpcException{
        Signatures sign = new Signatures();
        
        try {
            // aggiorno la CRL se non l'ho ancora richiesta o se è scaduta
            if(crl==null || crl.getNextUpdate().before(new Date())){

                crl=ottieniCrl();
            
            }
            
            // leggo il certificato dal file passato in input
            PEMReader pemReader= new PEMReader(new FileReader(certificato.getPath()));
            X509Certificate cert = (X509Certificate) pemReader.readObject();
            
            return(sign.verifySignatures(file, certCA, cert, crl));
        
            } catch (CRLException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            } catch (CertificateException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            } catch (GeneralSecurityException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        return 0;
    }
    
    
   /**
    * Critta un pdf con il certificato di crittografia passato in input
    * @param file : il certificato di crittografia
    * @return 0 se tutto è andato a buon fine
    * @throws IOException 
    * @throws DocumentException
    * @throws CertificateException  
    */
    public int crittaPdf(File file) throws IOException, DocumentException, CertificateException{
        EncryptWithCertificate encrypt = new EncryptWithCertificate();
        
            encrypt.encryptPdf(file.getPath(), file.getParent()+"/crittografato.pdf" , readCertificateFile(2));
            return 0;
        
        
    }

    /**
     * Decritta un file pdf con il certificato e la chiave privata del client
     * @param pdf 
     * @return 0 se tutto va bene, 1 altrimenti
     * @throws IOException 
     * @throws GeneralSecurityException
     * @throws XmlRpcException 
     * @throws DocumentException  
     */
    public int decrittaPdf(File pdf) throws XmlRpcException, GeneralSecurityException, DocumentException{
        EncryptWithCertificate encript = new EncryptWithCertificate();
        PEMReader pemReader = null;
        try {
            File certificato = new File("cert/myCrit.cert");
            // controllo la validità del certificato su CRL e OCSP
            /*if(controllaValidita(certificato)!=0){
                return 1;
            }*/
            pemReader = new PEMReader(new FileReader(certificato));
            X509Certificate cert = (X509Certificate) pemReader.readObject();

           
            System.out.println(pdf.getPath().toString()+" "+pdf.getName().toString());
            // decritto il pdf
            //encript.decryptPdf(pdf.getPath(), pdf.getParent()+"/decrittato.pdf", cert, kpCrit.getPrivate());
            encript.decryptPdf(pdf.getPath(), pdf.getParent()+"/decrittato.pdf", this.getPublicCertificate("cert/my.cert"), kpCrit.getPrivate());
            return 0;

        } catch (IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CRLException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CertificateException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                pemReader.close();
            } catch (IOException ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            }
        } 
        return 1;
    }
    
    
    /**
     * Controlla la validità di un certificato con CRL e OCSP
     * @param certificato
     * @return 0 se il certificato non è revocato, 1 altrimenti
     * @throws CRLException 
     * @throws CertificateException
     * @throws FileNotFoundException 
     * @throws IOException
     * @throws OCSPException 
     * @throws XmlRpcException  
     */
    public int controllaValidita(File certificato) throws CRLException, CertificateException, FileNotFoundException, IOException, OCSPException, XmlRpcException{
    
        int status=0;
        // leggo il certificato dal file passato in input
        PEMReader pemReader= new PEMReader(new FileReader(certificato));
        X509Certificate cert = (X509Certificate) pemReader.readObject();
        
        // controllo se la crl è scaduta. In tal caso la richiedo alla CA
        if(crl==null || crl.getNextUpdate().before(new Date())){
                crl=ottieniCrl();    
        }
        
        // se il serial number del certificato è presente nella crl, allora è revocato
        if(crl.getRevokedCertificate(cert.getSerialNumber())!=null){
            System.out.println("Certificato revocato secondo la CRL");
            status=1;
        }else{
            System.out.println("Certificato non revocato secondo la CRL");
        }
        
        // OCSP
                
        BigInteger serialNumber = cert.getSerialNumber();
        CertificateID id = new CertificateID(CertificateID.HASH_SHA1,cert, serialNumber);            
        // generazione richiesta standard OCSP
        OCSPReqGenerator gen = new OCSPReqGenerator();
        gen.addRequest(id);
        
        // crea e imposta nonce
        BigInteger nonce = BigInteger.valueOf(System.currentTimeMillis());
        Vector oids = new Vector();
        Vector values = new Vector();
        oids.add(OCSPObjectIdentifiers.id_pkix_ocsp_nonce);
        values.add(new X509Extension(false, new DEROctetString(nonce.toByteArray())));
        gen.setRequestExtensions(new X509Extensions(oids, values));
        OCSPReq req = gen.generate();


        byte[] certCoded = Base64.encode(req.getEncoded());
        String strCertCoded = new String(certCoded);  

        // Creo il file xml che contiene il parametro: certificato. Il file xml mi serve per firmarlo nel digsign
        Document richiestaXMLRevocaOCSP = XMLUtility.getDocumentCertificato(strCertCoded);

        // Firmo il documento
        richiestaXMLRevocaOCSP = XMLUtility.firmaDocumento(richiestaXMLRevocaOCSP, this.getPrivKey(), (PublicKey)this.pubKey);        

        /*
        * Parametri da inviare
        * Invio il documento xml firmato con i paramentri al suo interno
        * per una comunicazione sicura
        */
        Vector params = new Vector();            
        params.add(richiestaXMLRevocaOCSP);

        // faccio la richiesta
        Object result = this.xmlRcpClient.execute("ServiziCA.verificaOCSP", params);

        // leggo la OCSPResp dal documento ritornato dalla CA
        String ocspStringa = XMLUtility.getValueStringInXML((Document)result, "ocsp");                

            // Da stringa lo converto in byte e da byte in OCSPResp e poi in BasicResponse
            String strDecoded1 = ocspStringa;

        byte[] decoded = Base64.decode(strDecoded1);

        OCSPResp ocspResp = new OCSPResp(decoded);

        BasicOCSPResp basicResponse = (BasicOCSPResp) ocspResp.getResponseObject();

        if (basicResponse != null) {
            SingleResp[] responses = basicResponse.getResponses();
            if (responses.length == 1) {
            SingleResp resp = responses[0];

            System.out.println("This Update: " + resp.getThisUpdate());
            System.out.println("Next Update: " + resp.getNextUpdate());
            Object status2 = resp.getCertStatus();
            if (status2 == CertificateStatus.GOOD) {
                System.out.println("OCSP Status is good!");

            } else if (status2 instanceof
            org.bouncycastle.ocsp.RevokedStatus) {
                System.out.println("OCSP Status is revoked!");
                status=1;

                        }  else if (status2 instanceof
        org.bouncycastle.ocsp.UnknownStatus) {
                            System.out.println("OCSP Status is unknown!");
                            status=1;

                        }		  
                    }
                }

        return status;
    }
    
    public X509Certificate getPublicCertificate(String path)
        throws IOException, CertificateException {
        FileInputStream is = new FileInputStream(path);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
        return cert;
    }
    
}
